package com.hmkj.web.controller.trade;

import com.hmkj.common.entity.ResultEntity;
import com.hmkj.common.utils.PriceHelper;
import com.hmkj.common.utils.StringUtils;
import com.hmkj.core.constant.ConfigNID;
import com.hmkj.core.eolinker.endpoints.QuotationEndpoint;
import com.hmkj.core.eolinker.models.ModelRealTime;
import com.hmkj.core.exception.BussinessException;
import com.hmkj.core.model.BuyModel;
import com.hmkj.core.model.order.OrderModel;
import com.hmkj.core.po.account.Account;
import com.hmkj.core.po.order.Order;
import com.hmkj.core.po.user.User;
import com.hmkj.core.po.userFreeze.UserFreeze;
import com.hmkj.core.service.account.AccountService;
import com.hmkj.core.service.order.OrderService;
import com.hmkj.core.service.userFreeze.UserFreezeService;
import com.hmkj.web.controller.GenericController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ......................我佛慈悲......................
 * ......................_oo0oo_.......................
 * .....................o8888888o......................
 * .....................88" . "88......................
 * .....................(| -_- |)......................
 * .....................0\  =  /0......................
 * ...................___/`---'\___....................
 * ..................' \\|     |// '...................
 * ................/ \\|||  :  |||// \.................
 * .............../ _||||| -卍-|||||- \................
 * ..............|   | \\\  -  /// |   |...............
 * ..............| \_|  ''\---/''  |_/ |...............
 * ..............\  .-\__  '-'  ___/-. /...............
 * ............___'. .'  /--.--\  `. .'___.............
 * .........."" '<  `.___\_<|>_/___.' >' ""............
 * ........| | :  `- \`.;`\ _ /`;.`/ - ` : | |.........
 * ........\  \ `_.   \_ __\ /__ _/   .-` /  /.........
 * ....=====`-.____`.___ \_____/___.-`___.-'=====......
 * ......................`=---='.......................
 * ....................................................
 * .................佛祖开光 ,永无BUG...................
 */
@Api(description = "点买")
@Slf4j
@RestController
@RequestMapping(GenericController.MEMBER_URL + "/trade/buy")
public class AppBuyController extends GenericController<Integer, Order> {

    @Resource
    private OrderService orderService;
    @Resource
    private AccountService accountService;
    @Resource
    private UserFreezeService userFreezeService;

//    @ApiOperation(value = "点买页面初始化数据", notes = "点买页面初始化数据")
//    @RequestMapping(value = "/buyInitBakJson", method = RequestMethod.POST)
//    @ResponseBody
//    public ResultEntity buyInitBakJson(@ApiParam("点买金额") @RequestParam(required = true) BigDecimal level,
//                                    @ApiParam("股票代码") @RequestParam(required = true) String code) throws Exception {
//        User user = getLoginUser();
//        if (null == level || level.compareTo(BigDecimal.ZERO) != 1) {
//            throw new BussinessException("点买金额错误");
//        }
//        if (StringUtils.isBlank(code)) {
//            throw new BussinessException("股票代码为空");
//        }
//        ModelRealTime modelRealTime = QuotationEndpoint.realtime(code);
//        if (null == modelRealTime) {
//            throw new BussinessException("股票信息出错");
//        }
//        //点买本金 前台显示点买额度公分8档，单位：万元
//        String buyLevel = redisService.get(ConfigNID.BUY_LEVEL);
//        //最大止盈比例
//        BigDecimal stopProfitLine = redisService.get(ConfigNID.STOP_PROFIT_LINE, BigDecimal.class);
//        //杠杆比例
//        String[] losss = redisService.get(ConfigNID.LEVER_RATE).split(";");
//        //递延阈值
//        BigDecimal diyanLimit = redisService.get(ConfigNID.DIYAN_LIMIT, BigDecimal.class);
//        //盈利分成
//        String dividend = redisService.get(ConfigNID.DIVIDE_SCALE);
//        //行情最新价
//        BigDecimal price = new BigDecimal(modelRealTime.getLast_price());
//        //止盈线
//        if (StringUtils.isBlank(stopProfitLine)) {
//            throw new BussinessException("未设置止盈线");
//        }
//        Map<String, Object> data = new HashMap<>();
//        //止盈
//        BigDecimal stopProfit = stopProfitLine.multiply(level).multiply(new BigDecimal("10000"));
//        //交易综合费(元)（买入）
//        BigDecimal fee = level.multiply(redisService.get(ConfigNID.OVERALL_FEE, BigDecimal.class));
//        //递延费(正常)
//        BigDecimal defer = level.multiply(redisService.get(ConfigNID.DIYAN_FEE, BigDecimal.class));
//
//        //杠杆比例设置
//        List<StopLossModel> list = stopLossList(level, losss, stopProfit, fee, diyanLimit, defer, dividend);
//        data.put("stopLoss", list);
//
//        //可买股数(百股) 点买额度/（当前价*1.02）取整百
//        //计算当前价格*1.02的价格
//        BigDecimal priceAfter = price.multiply(new BigDecimal("1.02"));
//        //计算点买额度除以当前价格*1.02的数量
//        BigDecimal total = level.multiply(new BigDecimal("10000")).divide(priceAfter, 2);
//        //计算百股数
//        double number = total.doubleValue() / 100;
//        double totalNumber = Math.floor(number) * 100;
//        data.put("number", totalNumber);
//        //资金利用率  点买额度/（当前价*1.02）  * 当前价 / 点买额度
//        //计算 总股数✖ 当前价
//        double totalPrice = totalNumber * Double.parseDouble(String.valueOf(price));
//        //计算资金利用率
//        double use = BigDecimalUtils.div(totalPrice, Double.parseDouble(level.toString()) * 10000, 2);
//        data.put("use", use);
//
//        data.put("tradeCredit", buyLevel);
//        //系统配置的最大点买次数
//        Integer maxBuy = redisService.get(ConfigNID.ORDER_COUNT_LIMIT, Integer.class);
//        //计算当天可买次数
//        //当天点买订单数量
//        HashMap<String, Object> param = new HashMap<>();
//        param.put("userId", user.getId());
//        param.put("date", 1);
//        List<Order> buyList = orderService.selectOrderForTime(param);
//        Integer leftBuy = maxBuy - buyList.size();
//        if (leftBuy < 0) {
//            leftBuy = 0;
//        }
//        data.put("leftBuy", leftBuy);
//        return ok(data);
//    }
//
//    @ApiOperation(value = "提交订单", notes = "提交订单")
//    @RequestMapping(value = "/buyBakJson", method = RequestMethod.POST)
//    @ResponseBody
//    public ResultEntity buyBakJson(@ApiParam("股票代码") @RequestParam(required = true) String code,
//                               @ApiParam("点买额度") @RequestParam(required = true) BigDecimal tradeCredit,
//                               @ApiParam("履约保证金") @RequestParam(required = true) BigDecimal deposit,
//                               @ApiParam("交易综合费") @RequestParam(required = true) BigDecimal paidFee,
//                               @ApiParam("盈利分成比例") @RequestParam(required = true) BigDecimal divideScale,
//                               @ApiParam("止损线") @RequestParam(required = true) BigDecimal stopLossLine,
//                               @ApiParam("止盈线") @RequestParam(required = true) BigDecimal stopProfitLine,
//                               @ApiParam("止损价") @RequestParam(required = true) BigDecimal loseStopPrice,
//                               @ApiParam("止盈价") @RequestParam(required = true) BigDecimal profitStopPrice,
//                               @ApiParam("杠杆比例") @RequestParam(required = true) Integer levelRate,
//                               @ApiParam("递延条件") @RequestParam(required = true) BigDecimal lossLimit) throws Exception {
//        User user = getLoginUser();
//        //判断是否在交易时段
//        Integer isOpenTradeTime = redisService.get(ConfigNID.IS_OPEN_TRADE_TIME, Integer.class);
//        if (null == isOpenTradeTime || isOpenTradeTime == 1) {
//            if (!OrderModel.checkTradeDate()) {
//                new BussinessException("非交易时间");
//            }
//        }
//        //判断用户是否被冻结点买功能
//        UserFreeze freeze = userFreezeService.selectOne(new UserFreeze(t -> {
//            t.setUserId(user.getId());
//        }));
//        if (freeze != null) {
//            if (freeze.getFreezeTrade() == UserFreeze.FREEZETRADE.T2.code) {
//                throw new BussinessException("交易功能被冻结，请联系客服！");
//            }
//        } else {
//            throw new BussinessException("交易功能冻结异常！");
//        }
//        //获取当前股票的价格
//        ModelRealTime modelRealTime = QuotationEndpoint.realtime(code);
//        if (null == modelRealTime) {
//            throw new BussinessException("股票信息错误");
//        }
//        //校验点买参数
////        BuyModel buyModel = validBuyParams(user, tradeCredit, paidFee, deposit, stopLossLine, stopProfitLine, divideScale, loseStopPrice, profitStopPrice, lossLimit, levelRate, modelRealTime);
////        orderService.buyOrder(user, modelRealTime, buyModel);
//        return ok();
//    }

//    private List<StopLossModel> stopLossList(BigDecimal level, String[] losss, BigDecimal stopProfit, BigDecimal fee, BigDecimal diyanLimit, BigDecimal defer, String dividend) {
//        List<StopLossModel> list = new ArrayList<>();
//        for (int i = 0; i < losss.length; i++) {
//            StopLossModel model = new StopLossModel();
//            String[] loss = losss[i].split(",");
//            //杆杠倍数
//            String limit = loss[0];
//            //止损比例
//            String stop = loss[1];
//            //止损 = 点买金额/杆杠比例*止损比例
//            BigDecimal stopLoss = level.multiply(new BigDecimal("10000")).divide(new BigDecimal(limit), 2).multiply(new BigDecimal(stop)).negate();
//            stopLoss = stopLoss.setScale(0, BigDecimal.ROUND_HALF_UP);
//            //履约保证金 = 点买金额/杆杠比例
//            BigDecimal agreementScale = level.multiply(new BigDecimal("10000")).divide(new BigDecimal(limit), 2);
//            //递延条件 = 履约保证金 - 递延阈值*点买金额
//            BigDecimal diyanCondition = agreementScale.subtract((diyanLimit).multiply(level.multiply(new BigDecimal("10000"))));
//
//            model.setAgreementScale(agreementScale);
//            model.setStopLoss(stopLoss);
//            model.setDiyanCondition(diyanCondition.negate());
//            model.setFee(fee);
//            model.setDefer(defer);
//            model.setStopProfitLine(stopProfit);
//            model.setDividend(dividend);
//            model.setLevelRate(String.valueOf(i));
//            list.add(model);
//        }
//        return list;
//    }

    /**
     * 校验点买参数
     *
     * @param
     */
    private BuyModel validBuyParams(User user, Integer buyNum, BigDecimal paidFee, BigDecimal deposit, BigDecimal divideScale, BigDecimal loseStopPrice,
                                    BigDecimal profitStopPrice, BigDecimal lossLimit, BigDecimal loseDepositRate, ModelRealTime modelRealTime) throws BussinessException {
        BuyModel buyModel = new BuyModel();
        if (null == buyNum || null == paidFee || null == divideScale || null == deposit || null == loseStopPrice || null == profitStopPrice || null == loseDepositRate ||
                buyNum < 100 || buyNum.toString().length() > 10 ||
                paidFee.compareTo(BigDecimal.ZERO) < 0 ||
                divideScale.compareTo(BigDecimal.ZERO) < 0 ||
                divideScale.compareTo(BigDecimal.ONE) > 0 ||
                deposit.compareTo(BigDecimal.ZERO) < 0 ||
                loseStopPrice.compareTo(BigDecimal.ZERO) < 0 ||
                profitStopPrice.compareTo(BigDecimal.ZERO) < 0 ||
                loseDepositRate.compareTo(BigDecimal.ZERO) < 0 ||
                loseDepositRate.compareTo(BigDecimal.ONE) > 0) {
            throw new BussinessException("参数错误");
        }
        //行情最新价
        BigDecimal lastPrice = new BigDecimal(modelRealTime.getLast_price());
        //保证金需是1000的整倍数
        if (deposit.toString().length() > 7) {
            throw new BussinessException("信用金额度最大应小于7位数");
        }
        if (Double.parseDouble(deposit.toString()) % 1000 != 0) {
            throw new BussinessException("信用金需是1000的整倍数");
        }
        //市值 总股数✖ 当前价
        BigDecimal marketValue = lastPrice.multiply(new BigDecimal(buyNum));
        //计算点买额度 = 买入数量*当前价 向上万元取整（例：10001 ->> 20000），也就是市值向上万元取整
        BigDecimal tradeCredit = BigDecimal.ZERO;

        double pix = Double.parseDouble(marketValue.toString()) % 10000;
        if(pix != 0){
            tradeCredit = new BigDecimal(10000).add(marketValue.divide(new BigDecimal(10000),0,BigDecimal.ROUND_DOWN).multiply(new BigDecimal(10000)));
        }else{
            tradeCredit = marketValue;
        }
        //计算资金利用率 = 市值/点买额度
        BigDecimal use = marketValue.divide(tradeCredit, 2, BigDecimal.ROUND_DOWN);
        //交易综合费(元)（买入）
        BigDecimal confFee = tradeCredit.divide(new BigDecimal(10000), 2, BigDecimal.ROUND_UP).multiply(redisService.get(ConfigNID.OVERALL_FEE, BigDecimal.class));
        //最大止损保证金比例
        BigDecimal confLoseDepositRate = redisService.get(ConfigNID.MAX_STOP_LOSS_RATE, BigDecimal.class);
        //止盈比例
        BigDecimal stopProfitLine = redisService.get(ConfigNID.STOP_PROFIT_LINE, BigDecimal.class);

        //如果传过来的参数和计算的不一样，就报错
        if (!PriceHelper.isEquals(confFee, paidFee) || !PriceHelper.isEquals(confLoseDepositRate, loseDepositRate)) {
            throw new BussinessException("温馨提示：请刷新页面再进行购买。");
        }
        //计算最大止损价格 = 最新价 - 履约保证金*最大止损保证金比例/买入数量
        BigDecimal maxStopLosePrice = lastPrice.subtract(deposit.multiply(loseDepositRate).divide(new BigDecimal(buyNum), 2, BigDecimal.ROUND_UP));

        //计算止盈价格 = 最新价+止盈浮动
        BigDecimal confStopProfit = lastPrice.add(tradeCredit.multiply(stopProfitLine).divide(new BigDecimal(buyNum), 2, BigDecimal.ROUND_DOWN));

        if (loseStopPrice.compareTo(lastPrice) != -1) {
            throw new BussinessException("止损价格应小于当前价");
        } else if (loseStopPrice.compareTo(maxStopLosePrice) == -1) {
            throw new BussinessException("止损价格应大于" + maxStopLosePrice);
        }

        if (profitStopPrice.compareTo(lastPrice) != 1) {
            throw new BussinessException("止盈价格应大于当前价");
        } else if (profitStopPrice.compareTo(confStopProfit) == 1) {
            throw new BussinessException("止盈价格应小于" + confStopProfit);
        }

        //查询用户是否有足够的钱支付履约保证金和交易综合费
        Account account = accountService.selectByUID(user.getId());
        //用户可用资金
        BigDecimal available = account.getAvailable();
        //履约保证金+交易综合费
        BigDecimal total = deposit.add(paidFee);
        if (available.compareTo(total) < 0) {
            throw new BussinessException("策略余额不足，请充值");
        }
        //同一个用户 每天只能点买XX次
        HashMap<String, Object> param = new HashMap<>();
        param.put("date", 1);
        param.put("userId", user.getId());
        List<Order> list = orderService.selectOrderForTime(param);
        //获取点买人每天最多点买次数
        Integer orderCount = redisService.get(ConfigNID.ORDER_COUNT_LIMIT, Integer.class);
        if (null != list && list.size() >= orderCount) {
            throw new BussinessException("您已达到点买上限！");
        }
        buyModel.setBuyNumber(buyNum);
        buyModel.setUseRatio(use);
        buyModel.setTradeCredit(tradeCredit.divide(new BigDecimal(10000), 2, BigDecimal.ROUND_UP));
        buyModel.setPaidFee(paidFee);
        buyModel.setDeposit(deposit);
        buyModel.setProfitStopPrice(profitStopPrice);
        buyModel.setLoseStopPrice(loseStopPrice);
        buyModel.setDivideScale(divideScale);
        buyModel.setLossLimit(lossLimit);
        buyModel.setLossRate(loseDepositRate);
        return buyModel;
    }

    @ApiOperation(value = "点买页面初始化数据", notes = "点买页面初始化数据")
    @RequestMapping(value = "/buyInitJson", method = RequestMethod.POST)
    @ResponseBody
    public ResultEntity buyInitJson(@ApiParam("股票代码") @RequestParam(required = true) String code) throws Exception {
        // 1.获取用户信息及参数校验
        User user = getLoginUser();
        if (StringUtils.isBlank(code)) {
            throw new BussinessException("股票代码为空");
        }
        // 2.获取实时股票行情
        ModelRealTime modelRealTime = QuotationEndpoint.realtime(code);
        if (null == modelRealTime) {
            throw new BussinessException("股票信息出错");
        }
        Map<String, Object> data = new HashMap<>();
        //点买保证金额度
        String buyLevel = redisService.get(ConfigNID.BUY_LEVEL);
        //止盈比例
        BigDecimal stopProfitLine = redisService.get(ConfigNID.STOP_PROFIT_LINE, BigDecimal.class);
        //递延阈值
        BigDecimal diyanLimit = redisService.get(ConfigNID.DIYAN_LIMIT, BigDecimal.class);
        //盈利分成
        String dividend = redisService.get(ConfigNID.DIVIDE_SCALE);
        //手续费/万元 综合费用
        BigDecimal fee = redisService.get(ConfigNID.OVERALL_FEE, BigDecimal.class);
        //递延费
        BigDecimal diyanFee = redisService.get(ConfigNID.DIYAN_FEE, BigDecimal.class);
        //最大止损保证金比例
        BigDecimal loseDepositRate = redisService.get(ConfigNID.MAX_STOP_LOSS_RATE, BigDecimal.class);
        //杠杆比例
        BigDecimal leveRate = redisService.get(ConfigNID.LEVER_RATE, BigDecimal.class);
        //止盈线
        if (StringUtils.isBlank(buyLevel)) {
            throw new BussinessException("未设置点买档位");
        }
        if (StringUtils.isBlank(stopProfitLine)) {
            throw new BussinessException("未设置止盈线");
        }
        if (null == diyanLimit) {
            throw new BussinessException("未设置递延阈值");
        }
        if (StringUtils.isBlank(dividend)) {
            throw new BussinessException("未设置盈利分成");
        }
        if (StringUtils.isBlank(fee)) {
            throw new BussinessException("未设置手续费");
        }
        if (null == leveRate) {
            throw new BussinessException("未设置杠杆比例");
        }
        String[] level = buyLevel.split(";");
        List<BigDecimal> lvDepositAttr = new ArrayList();
        for (int i = 0; i < level.length; i++) {
            lvDepositAttr.add(new BigDecimal(level[i]));
        }
        data.put("levelDeposit", lvDepositAttr);
        data.put("stopProfitLine", stopProfitLine);
        data.put("diyanLimit", diyanLimit);
        data.put("dividend", dividend);
        data.put("fee", fee);
        data.put("diyanFee", diyanFee);
        data.put("loseDepositRate", loseDepositRate);
        data.put("leveRate", leveRate);

        //系统配置的最大点买次数
        Integer maxBuy = redisService.get(ConfigNID.ORDER_COUNT_LIMIT, Integer.class);
        //计算当天可买次数
        //当天点买订单数量
        HashMap<String, Object> param = new HashMap<>();
        param.put("userId", user.getId());
        param.put("date", 1);
        List<Order> buyList = orderService.selectOrderForTime(param);
        Integer leftBuy = maxBuy - buyList.size();
        if (leftBuy < 0) {
            leftBuy = 0;
        }
        // 可卖订单数量
        data.put("leftBuy", leftBuy);
        // 账户的可用余额
        data.put("avaliable",accountService.selectByUID(user.getId()).getAvailable());
        return ok(data);
    }

    @ApiOperation(value = "提交订单", notes = "提交订单")
    @RequestMapping(value = "/buyJson", method = RequestMethod.POST)
    @ResponseBody
    public ResultEntity buJson(@ApiParam("股票代码") @RequestParam(required = true) String code,
                               @ApiParam("履约保证金") @RequestParam(required = true) BigDecimal deposit,
                               @ApiParam("交易综合费") @RequestParam(required = true) BigDecimal paidFee,
                               @ApiParam("买入数量") @RequestParam(required = true) Integer buyNum,
                               @ApiParam("盈利分成比例") @RequestParam(required = true) BigDecimal divideScale,
                               @ApiParam("最大止损比例") @RequestParam(required = true) BigDecimal loseDepositRate,
                               @ApiParam("止损价") @RequestParam(required = true) BigDecimal loseStopPrice,
                               @ApiParam("止盈价") @RequestParam(required = true) BigDecimal profitStopPrice,
                               @ApiParam("递延条件") @RequestParam(required = true) BigDecimal lossLimit) throws Exception {
        User user = getLoginUser();
        //判断是否在交易时段
        Integer isOpenTradeTime = redisService.get(ConfigNID.IS_OPEN_TRADE_TIME, Integer.class);
        if (null == isOpenTradeTime || isOpenTradeTime == 1) {
            if (!OrderModel.checkTradeDate()) {
                new BussinessException("非交易时间");
            }
        }
        //判断用户是否被冻结点买功能
        UserFreeze freeze = userFreezeService.selectOne(new UserFreeze(t -> {
            t.setUserId(user.getId());
        }));
        if (freeze != null) {
            if (freeze.getFreezeTrade() == UserFreeze.FREEZETRADE.T2.code) {
                throw new BussinessException("交易功能被冻结，请联系客服！");
            }
        } else {
            throw new BussinessException("交易功能冻结异常！");
        }
        //获取当前股票的价格
        ModelRealTime modelRealTime = QuotationEndpoint.realtime(code);
        if (null == modelRealTime) {
            throw new BussinessException("股票信息错误");
        }
        //校验点买参数
        BuyModel buyModel = validBuyParams(user, buyNum, paidFee, deposit, divideScale, loseStopPrice, profitStopPrice, lossLimit, loseDepositRate, modelRealTime);
        orderService.buyOrder(user, modelRealTime, buyModel);
        return ok("提交订单成功", ResultEntity.SUCCESS);
    }
}
